import threading, time
from collections import deque

import sk_input, sk_math, sk_map
import ent, ent_furniture
import astar2

class Pathfinder(threading.Thread):
	
	def __init__(self):
		threading.Thread.__init__(self)

		self.ai_pool = deque([])
		self.processing = None
		self.em = None
		
	def set_em(self,em):
		self.em = em	

	def add_request(self,ai):
		if (ai not in self.ai_pool) and (self.processing != ai):
			self.ai_pool.append(ai)
			
			
	def calculate_path(self, ai):
		map = 		self.em.services["map"]
		objects = 	self.em.services["objects"]
		owner = ai.owner
		
		target = ai.target

		def neighbors(pos):
			i,j = pos
			#return map.graph[map.tiles[i][j]]
			nbrs = []
			for nb in ( (i,j+1), (i,j-1), (i-1,j), (i+1,j) ):
				x,y = nb
				
				nb_limit = sk_map.CHUNK_SIZE/2
				
				if x > owner.x - nb_limit and x < owner.x + nb_limit and y > owner.y - nb_limit and y < owner.y + nb_limit:
					tile = map.get_tile(x,y)
					if tile and not tile.blocked:
						nbrs.append((x,y))
					
			#print nbrs
			
			return nbrs

		def goal(pos):
			return pos == (target.x,target.y)
            
		def cost(from_pos, to_pos):
			from_y, from_x = from_pos
			to_y, to_x = to_pos
			
			tile = map.get_tile(to_y,to_x)
			
			#do not allow to traven in circles
			if to_y - from_y and to_x - from_x:
				cost = 12
			else:
				cost = 10
				
			#do not allow to travel on restricted territory	
			__trespassing = False	
			if not owner in tile.owners:
				__trespassing = True
				cost  = cost * 10
				

			#do not allow to travel through window
			
			if tile.obstacle and not __trespassing:
				if isinstance(tile.objects[0],ent_furniture.Door):
					return 100
	
				#make huge penalty for trying to access building via window
				return 10000
	
				
			return cost

		def estimate(pos):
			y, x = pos
			dy, dx = abs(target.y - y), abs(target.x - x)
			return min(dy, dx) * 14 + abs(dy - dx) * 10

		def debug(nodes):
			#print nodes
			pass

		ai.path = astar2.astar((owner.x, owner.y), neighbors, goal, 0, cost, estimate, (sk_map.CHUNK_SIZE * sk_map.CHUNK_SIZE)/2, debug)		
		#print ai.path
			
	def run(self):
		
		_input = self.em.services["input"]
		
		while(_input.last_action != "exit"):
			time.sleep(0.5)

			while len(self.ai_pool):
				ai = self.ai_pool.popleft()
				self.processing = ai
			
				#calc path
				#print "FOUND PATH!"
				self.calculate_path(ai)

				self.processing = None
